﻿using Lsk.Business.DTO;
using Lsk.Data;
using System;
using System.Collections.Generic;
using System.Data.Entity.Core.Objects;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Validation;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Lsk.Business
{
    public class Property
    {
        private Lsk.Data.lskEntities _entity;
      
        public Property()
        {
            _entity = new lskEntities();
           
          
        }


        public IEnumerable<GetState_Result> GetState()
        {
            ObjectResult<GetState_Result> state = _entity.GetState();
            return state.AsEnumerable();
        }


        public IEnumerable<GetLocationByStateId_Result> GetLocation(string id)
        {
            ObjectResult<GetLocationByStateId_Result> locations = _entity.GetLocationByStateId(id);
            return locations.AsEnumerable();
        }

        public IEnumerable<GetRoadName_Result> GetRoadName(string id)
        {
            ObjectResult<GetRoadName_Result> roadNames = _entity.GetRoadName(id);
            return roadNames.AsEnumerable();
        }

        public IEnumerable<GetProject_Result> GetProject(string id)
        {
            ObjectResult<GetProject_Result> project = _entity.GetProject(id);
            return project.AsEnumerable();
        }

        public IEnumerable<AW_PropertyType> GetPropertyType()
        {
            IEnumerable<AW_PropertyType> data = (from a in _entity.AW_PropertyType where a.StatusDelete ==0  orderby a.Type select a );             
            return data;
        }

        public ResponseMessage GetProperty(string id)
        {         
            ResponseMessage data = new ResponseMessage();
            data = GetPropertyById(id);
            return data;
        }


        /// <summary>
        /// For Listing Entry
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        private ResponseMessage GetPropertyById(string id)
        {
            ResponseMessage result = new ResponseMessage();
            GetPropertyById_Result data = _entity.GetPropertyById(new Guid(id)).FirstOrDefault();
            IEnumerable<GetRoadName_Result> road = _entity.GetRoadName(data.LocationId.ToString()).ToList();
            IEnumerable<GetProject_Result> project = _entity.GetProject(data.RoadId.ToString()).ToList();
            IEnumerable<GetLocationByStateId_Result> location = _entity.GetLocationByStateId(data.StateId.ToString()).ToList();
            IEnumerable<GetState_Result> state = _entity.GetState();
            
            int pictureCount = (from a in _entity.AW_Picture where a.PropertyId == new Guid(id) select a).Count();
            IEnumerable<GetPictureByID_Result> picture;
            if (pictureCount > 0)
            {
                picture = _entity.GetPictureByID(data.PropertyId.ToString()).ToList();
                result.pictureList = picture;
            }

            result.property = data;
            result.locationList = location;
            result.projectList = project;
            result.roadList = road;
            result.stateList = state;
          
            return result;
        }

        /// <summary>
        /// For Getting Property Details By Id -- NOT USING OBSOLETE
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public ResponseMessage GetPropertyDetailById(string id)
        {
            ResponseMessage result = new ResponseMessage();
            GetPropertyDetail_Result data=  _entity.GetPropertyDetail(new Guid(id)).FirstOrDefault();
            //GetPropertyById_Result data = _entity.GetPropertyById(new Guid(id)).FirstOrDefault();
            ObjectResult<GetSalePropertyNearBy_Result> nearByResult   = _entity.GetSalePropertyNearBy("SC", 0, 0, 0, 0,"",2, 0, 20, data.Latitude, data.Longitude, 5);
            int pictureCount = (from a in _entity.AW_Picture where a.PropertyId == new Guid(id) select a).Count();
            IEnumerable<GetPictureByID_Result> picture;
            if (pictureCount > 0)
            {
                picture = _entity.GetPictureByID(data.propertyid.ToString()).ToList();
                result.pictureList = picture;
            }

            //result.propertyDetail = data;
            result.nearByListSale = nearByResult;
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <param name="listType"></param>
        /// <returns></returns>
        public ResponseMessage GetPropertyDetailByListType(string id, string listType)
        {
            ResponseMessage result = new ResponseMessage();
            //GetPropertyDetail_Result data = _entity.GetPropertyDetail(new Guid(id)).FirstOrDefault();
            GetPropertyDetailV2_Result data = _entity.GetPropertyDetailV2(new Guid(id), listType.Substring(0, 1)).FirstOrDefault();

            // Get the nearby property and also retrieve agent info
            if (listType[0] == 'S')
            {
                ObjectResult<GetSalePropertyNearBy_Result> nearByResult = _entity.GetSalePropertyNearBy(listType, 0, 0, 0, 0, "", 2, 0, 20, data.Latitude, data.Longitude, 5);
                result.nearByListSale = nearByResult;
            }
            else
            {
                ObjectResult<GetRentPropertyNearBy_Result> nearByResult = _entity.GetRentPropertyNearBy(listType, 0, 0, 0, 0, "", 2, 0, data.Latitude, data.Longitude, 5);
                result.nearByListRent = nearByResult;
            }
            int pictureCount = (from a in _entity.AW_Picture where a.PropertyId == new Guid(id) select a).Count();
            IEnumerable<GetPictureByID_Result> picture;
            if (pictureCount > 0)
            {
                picture = _entity.GetPictureByID(data.propertyid.ToString()).ToList();
                result.pictureList = picture;
            }

            result.propertyDetail = data;
            
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <param name="listType"></param>
        /// <returns></returns>
        public ResponseMessage GetPropertyDetailByLatLng(decimal lng, decimal lat, int distant, string listType)
        {
            ResponseMessage result = new ResponseMessage();

            // Get the nearby property and also retrieve agent info
            if (listType[0] == 'S')
            {
                ObjectResult<GetSalePropertyNearBy_Result> nearByResult = _entity.GetSalePropertyNearBy(listType, 0, 0, 0, 0, "", 2, 0, 20, lat, lng, distant);
                result.nearByListSale = nearByResult;
            }
            else
            {
                ObjectResult<GetRentPropertyNearBy_Result> nearByResult = _entity.GetRentPropertyNearBy(listType, 0, 0, 0, 0, "", 2, 0, lat, lng, distant);
                result.nearByListRent = nearByResult;
            }
            return result;
        }

        public IEnumerable<GetNearByProperty_Result> GetPropertiesByTypeLatLng(decimal lng, decimal lat, int distant, string listType)
        {
            // Get the nearby property and also retrieve agent info
            ObjectResult<GetNearByProperty_Result> nearByResult = _entity.GetNearByProperty(listType, lat, lng, distant);                

            return nearByResult.AsEnumerable();
        }
        //public ResponseMessage SaveListing(ListingEntry data)
        //{
        //    ResponseMessage msg = new ResponseMessage();
        //    ObjectResult<Guid?> projectId = _entity.SaveListing(data.PropertyId,data.ListTypeId,data.StateId,data.LocationId,data.RoadId,data.ProjectId);
        //    msg.Message = projectId.ToString();
        //    return msg;
        //}

        public ResponseMessage GetListing(string id)
        {
            ResponseMessage msg = new ResponseMessage();            
            msg.property = _entity.GetPropertyById(new Guid(id)).FirstOrDefault();
            return msg;
        }


        public ResponseMessage SaveListing(AW_Property data)
        {
            ResponseMessage msg = new ResponseMessage();
            try
            {
                if (data.PropertyId == new Guid("00000000-0000-0000-0000-000000000000"))
                {
                    // must check if the existing property already has similar roadid,locationid ,stateid, and unit number, projectid
                    // if exist, don't allow to create to prevent double listing
                    
                    bool exists = _entity.AW_Property.Any(a => a.UnitNumber == data.UnitNumber && a.RoadId == data.RoadId && (a.StatusDelete == 0 || a.StatusDelete == null));
                    if (!exists)
                    {
                        data.PropertyId = Guid.NewGuid();
                        data.CreateDate = DateTime.Now;
                        data.ListType = (byte)data.ListType;
                        data.StatusDelete = 0;

                        if (data.SRYes.ToString() == "1") { data.SRCreateDate = DateTime.Now; data.SRelistStatus = 0; data.SRPSF = (data.BUSF > 0) ? (data.SRAmt / data.BUSF) : 0; }
                        if (data.SCYes.ToString() == "1") { data.SCCreateDate = DateTime.Now; data.SRelistStatus = 0; data.SCPSF = (data.BUSF > 0) ? (data.SCAmt / data.BUSF) : 0; }
                        if (data.SLYes.ToString() == "1") { data.SLCreateDate = DateTime.Now; data.SRelistStatus = 0; data.SLPSF = (data.BUSF > 0) ? (data.SLAmt / data.BUSF) : 0; }
                        if (data.SIYes.ToString() == "1") { data.SICreateDate = DateTime.Now; data.SRelistStatus = 0; data.SIPSF = (data.BUSF > 0) ? (data.SIAmt / data.BUSF) : 0; }

                        if (data.RRYes.ToString() == "1") { data.RRCreateDate = DateTime.Now; data.RRelistStatus = 0; data.RRPSF = (data.BUSF > 0) ? (data.RRAmt / data.BUSF) : 0; }
                        if (data.RCYes.ToString() == "1") { data.RCCreateDate = DateTime.Now; data.RRelistStatus = 0; data.RCPSF = (data.BUSF > 0) ? (data.RCAmt / data.BUSF) : 0; }
                        if (data.RLYes.ToString() == "1") { data.RLCreateDate = DateTime.Now; data.RRelistStatus = 0; data.RLPSF = (data.BUSF > 0) ? (data.RLAmt / data.BUSF) : 0; }
                        if (data.RIYes.ToString() == "1") { data.RICreateDate = DateTime.Now; data.RRelistStatus = 0; data.RIPSF = (data.BUSF > 0) ? (data.RIAmt / data.BUSF) : 0; }

                        _entity.AW_Property.Add(data);
                        _entity.SaveChanges().ToString();
                    }
                    else
                    {
                        AW_Property dataProperty = (from a in _entity.AW_Property where a.UnitNumber.Equals(data.UnitNumber) && a.RoadId.Equals(data.RoadId) && a.StatusDelete.Equals(0) select a).FirstOrDefault();
                        data = dataProperty;                        
                    }
                }
                else
                {
                     AW_Property dataProperty = (from a in _entity.AW_Property where a.PropertyId == data.PropertyId select a).FirstOrDefault();
                     data.ListType = (byte)data.ListType;
                     //dataProperty = data;
                     //_entity.SaveChanges();  Don't save changes if the property already exist in the system.
                }
                //AW_Property output = (from a in _entity.AW_Property where a.PropertyId == data.PropertyId select a).FirstOrDefault();
                GetPropertyById_Result output=  _entity.GetPropertyById(data.PropertyId).FirstOrDefault();
                msg.Message = data.PropertyId.ToString();
                msg.property = output;
                return msg;
            }

            catch (DbEntityValidationException e)
            {
                string message;
                foreach (var eve in e.EntityValidationErrors)
                {
                    message = string.Format("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
                        eve.Entry.Entity.GetType().Name, eve.Entry.State);
                    foreach (var ve in eve.ValidationErrors)
                    {
                        message = message + string.Format("- Property: \"{0}\", Error: \"{1}\"",
                            ve.PropertyName, ve.ErrorMessage);
                    }
                    msg.Message = message;
                }
               
            }
            return msg;
        }

        public void DeletePictureByPhotoId(string photoId)
        {
            _entity.DeletePictureByPhotoId(photoId);
        }
    }
}
